<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>声音控制</title>
</head>

<body>
    <div id="types">

    </div>
    <button onclick="create(this)">开始播放</button>
</body>
<script>
    const audio_data_list = [261.63, 293.66, 329.63, 349.23, 392.00, 440.00, 493.88, 261.63 * 2].map(v => v)
    const audio_type_list = ['sine', 'square', 'sawtooth', 'triangle']
    let typeIndex = 1
    let index = 0
    document.getElementById('types').innerHTML = `音调类型: ` + audio_type_list.map((v, i) => {
        return `<button onclick="setType(${i})">${v}</button> `
    }).join('') + `<span id="selType">${audio_type_list[typeIndex]}</span>`
    function setType(i) {
        typeIndex = i.toString()
        document.getElementById('selType').innerHTML = audio_type_list[i]
    }
    function create(me) {
        let volBl = 0.1
        me.innerHTML = `基础音：${index === 7 ? '+1' : (index + 1)}`
        // 创建音频上下文  
        const audioCtx = new AudioContext();
        // 创建音调控制对象  
        const oscillator = audioCtx.createOscillator();
        // 创建音量控制对象  
        const gainNode = audioCtx.createGain();
        // 音调音量关联  
        oscillator.connect(gainNode);
        // 音量和设备关联  
        gainNode.connect(audioCtx.destination);
        // 音调类型指定为正弦波  
        oscillator.type = audio_type_list[typeIndex];
        // 设置音调频率  
        oscillator.frequency.value = audio_data_list[index];
        // oscillator.frequency.value = 2000;
        // 先把当前音量设为0  
        gainNode.gain.setValueAtTime(0, audioCtx.currentTime);
        // 0.01秒时间内音量从刚刚的0变成1，线性变化 
        gainNode.gain.linearRampToValueAtTime(1 * volBl, audioCtx.currentTime + 0.01);
        // 声音走起 
        oscillator.start(audioCtx.currentTime);
        // 1秒时间内音量从刚刚的1变成0.001，指数变化 
        gainNode.gain.exponentialRampToValueAtTime(0.1 * volBl, audioCtx.currentTime + 1);
        // 1秒后停止声音 
        oscillator.stop(audioCtx.currentTime + 1);
        if (index >= audio_data_list.length - 1) {
            index = 0
        } else {
            index++
        }
    }

</script>

</html>